using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI; // 引入UI命名空间以使用Slider组件

/// <summary>
/// 范围进度控制器：实现两个阵营间的互相检测，当物体持续处于指定范围内时降低进度条，进度条为0时触发事件
/// 核心功能：
/// - 支持两个阵营标签的互相检测
/// - 基于坐标范围的检测模式
/// - 可配置进度条初始值、降低速度和恢复速度
/// - 提供进度变化事件和完成事件回调
/// - 包含详细的参数验证和状态管理
/// </summary>
public class RangeProgressController : MonoBehaviour
{
    #region 检测模式枚举
    /// <summary>
    /// 范围检测模式
    /// - Collider: 使用碰撞器触发检测（需要设置IsTrigger=true）
    /// - Position: 使用坐标范围检测（通过代码判断位置）
    /// </summary>
    /// <summary>
    /// 阵营检测类型
    /// - Attacker: 攻击者阵营标签
    /// - Target: 目标阵营标签
    /// </summary>
    public enum CampType
    {
        Attacker,
        Target
    }

    /// <summary>
    /// 范围检测模式
    /// - Position: 使用坐标范围检测（通过代码判断位置）
    /// </summary>
    public enum DetectionMode
    {
        Position
    }
    #endregion

    #region 可配置参数
    [Header("检测设置")]
    [Tooltip("范围检测模式：Position(坐标范围检测)")]
    public DetectionMode detectionMode = DetectionMode.Position;

    [Header("阵营标签设置")]
    [Tooltip("攻击者阵营标签")]
    [SerializeField]
    private string _attackerTag = "Attacker";
    [Tooltip("攻击者阵营标签")]
    public string attackerTag
    {
        get => _attackerTag;
        set
        {
            if (_attackerTag != value)
            {
                _attackerTag = value;
                if (Application.isPlaying)
                {
                    RefreshCampObjects();
                }
            }
        }
    }

    [Tooltip("目标阵营标签")]
    [SerializeField]
    private string _targetTag = "Target";
    [Tooltip("目标阵营标签")]
    public string targetTag
    {
        get => _targetTag;
        set
        {
            if (_targetTag != value)
            {
                _targetTag = value;
                if (Application.isPlaying)
                {
                    RefreshCampObjects();
                }
            }
        }
    }

    [Tooltip("目标阵营标签（在Inspector中选择）")]
    [HideInInspector] public Transform rangeCenterObject; // 保留此字段用于向后兼容

    [Header("范围大小设置")]
        [Tooltip("检测距离范围（半径）")]
        public float distanceRange = 5f;

    [Header("进度条设置")]
    [Tooltip("进度条初始值(0-100)")]
    [Range(0, 100)] public float initialProgress = 100f;

    [Tooltip("在范围内时的进度降低速度(单位：/秒)")]
    public float decreaseRate = 10f;

    [Tooltip("不在范围内时的进度恢复速度(单位：/秒)，设为0则不恢复")]
    public float recoveryRate = 5f;

    [Tooltip("是否允许进度条超过初始值")]
    public bool allowProgressOverMax = false;

    [Header("UI引用")]
    [Tooltip("用于显示进度的Slider组件，拖拽Slider到此处关联")]
    public Slider progressSlider;

    [Header("事件设置")]
    [Tooltip("进度条变为0时触发的事件")]
    public UnityEvent onProgressComplete;

    [Tooltip("进度值变化时触发的事件(参数：当前进度百分比)")]
    public UnityEvent<float> onProgressChanged;
    #endregion

    #region 私有变量
    private float _currentProgress;
    private bool _isInRange = false;
    private GameObject[] _attackerObjects; // 攻击者阵营物体列表
    private GameObject[] _targetObjects; // 目标阵营物体列表

    #endregion

    #region 属性
    /// <summary>
    /// 当前进度值(0-100)
    /// </summary>
    public float CurrentProgress
    {
        get => _currentProgress;
        private set
        {
            // 限制进度值在0-100范围内
            float clampedValue = Mathf.Clamp(value, 0, allowProgressOverMax ? Mathf.Infinity : initialProgress);
            if (!Mathf.Approximately(_currentProgress, clampedValue))
            {
                _currentProgress = clampedValue;
                onProgressChanged?.Invoke(_currentProgress);

                // 更新Slider值（如果已分配）
                if (progressSlider != null)
                {
                    progressSlider.value = _currentProgress / initialProgress; // 将进度归一化到0-1范围
                }

                // 检查进度是否为0，触发完成事件
                if (Mathf.Approximately(_currentProgress, 0) && onProgressComplete != null)
                {
                    onProgressComplete.Invoke();
                }
            }
        }
    }

    /// <summary>
    /// 是否正在范围内
    /// </summary>
    public bool IsInRange => _isInRange;
    #endregion

    #region 生命周期方法
    /// <summary>
    /// 初始化组件和进度值
    /// </summary>
    private void Awake()
    {
        _currentProgress = initialProgress;
        // 验证范围大小
        if (distanceRange <= 0)
        {
            Debug.LogWarning("检测距离必须为正数！已设置为默认值。", this);
            distanceRange = 5f;
        }

        // 验证初始进度
        if (initialProgress <= 0)
        {
            Debug.LogWarning("初始进度必须为正数！已设置为默认值100。", this);
            initialProgress = 100f;
        }

        // 验证进度参数
        if (decreaseRate <= 0)
        {
            Debug.LogWarning("降低速度必须为正数！已设置为默认值。", this);
            decreaseRate = 10f;
        }

        if (recoveryRate < 0)
        {
            Debug.LogWarning("恢复速度不能为负数！已设置为默认值。", this);
            recoveryRate = 5f;
        }

        // 验证阵营标签设置
        if (!IsTagValid(attackerTag))
        {
            Debug.LogError($"攻击者标签 '{attackerTag}' 无效或未设置！", this);
        }
        if (!IsTagValid(targetTag))
        {
            Debug.LogError($"目标标签 '{targetTag}' 无效或未设置！", this);
        }

        // 初始化阵营物体列表
        RefreshCampObjects();
    }

    /// <summary>
    /// 每帧更新进度条状态
    /// </summary>
    private void Update()
    {
        // 如果是坐标检测模式，更新是否在范围内的状态
        if (detectionMode == DetectionMode.Position)
        {
            CheckPositionInRange();
        }

        // 更新进度值
        UpdateProgress();
    }


    #endregion

    #region 核心逻辑方法
    /// <summary>
    /// 刷新标签物体列表并更新进度条
    /// </summary>
    /// <summary>
    /// 刷新阵营物体列表
    /// </summary>
    private void RefreshCampObjects()
    {
        _attackerObjects = GameObject.FindGameObjectsWithTag(attackerTag);
        _targetObjects = GameObject.FindGameObjectsWithTag(targetTag);

        if (_attackerObjects.Length == 0)
        {
            Debug.LogWarning($"[RangeProgressController] 未找到标签为'{attackerTag}'的物体！", this);
        }
        CheckPositionInRange(); // 立即更新范围检测状态
        UpdateProgress(); // 更新进度条显示
    }

    /// <summary>
    /// 检查物体是否在坐标范围内（坐标检测模式）
    /// </summary>
    private void CheckPositionInRange()
    {
        // 获取当前物体所属阵营
        bool isAttacker = gameObject.CompareTag(attackerTag);
        bool isTarget = gameObject.CompareTag(targetTag);

        if (!isAttacker && !isTarget)
        {
            _isInRange = false; // 不属于任何阵营，不检测
            return;
        }

        Vector3 objectPosition = transform.position;
        Vector2 localPosXZ = new Vector2(objectPosition.x, objectPosition.z);
        _isInRange = false;

        // 根据当前物体阵营检测对立阵营物体
        if (isAttacker && _targetObjects != null)
        {
            foreach (var targetObj in _targetObjects)
            {
                if (targetObj == null) continue;
                Vector3 targetPos = targetObj.transform.position;
                Vector2 targetPosXZ = new Vector2(targetPos.x, targetPos.z);
                float currentDistance = Vector2.Distance(localPosXZ, targetPosXZ);
                
                if (currentDistance <= distanceRange)
            {
                _isInRange = true;
                // 设置目标阵营物体的进度条状态
                RangeProgressController targetController = targetObj.GetComponent<RangeProgressController>();
                if (targetController != null)
                {
                    targetController.SetInRangeStatus(true);
                }
                return;
            }
            }
        }
        else if (isTarget && _attackerObjects != null)
        {
            foreach (var attackerObj in _attackerObjects)
            {
                if (attackerObj == null) continue;
                Vector3 attackerPos = attackerObj.transform.position;
                Vector2 attackerPosXZ = new Vector2(attackerPos.x, attackerPos.z);
                float currentDistance = Vector2.Distance(localPosXZ, attackerPosXZ);
                
                if (currentDistance <= distanceRange)
            {
                _isInRange = true;
                // 设置攻击者阵营物体的进度条状态
                RangeProgressController attackerController = attackerObj.GetComponent<RangeProgressController>();
                if (attackerController != null)
                {
                    attackerController.SetInRangeStatus(true);
                }
                return;
            }
            }
        }

        // 调试日志：显示距离信息
        // Debug.LogFormat("当前距离: {0:F2}, 范围: {1}, 是否在范围内: {2}", distance, distanceRange, inRange);
    }

    /// <summary>
    /// 更新进度条值
    /// </summary>
    private void UpdateProgress()
    {
        if (_isInRange)
        {
            // 在范围内，降低进度
            float newProgress = CurrentProgress - decreaseRate * Time.deltaTime;
            CurrentProgress = Mathf.Max(newProgress, 0); // 确保进度不小于0
        }
        else if (recoveryRate > 0)
        {
            // 不在范围内且恢复速度大于0，恢复进度
            float newProgress = CurrentProgress + recoveryRate * Time.deltaTime;
            CurrentProgress = allowProgressOverMax ? newProgress : Mathf.Min(newProgress, initialProgress);
        }
    }
    #endregion

    #region 公共方法
    /// <summary>
    /// 重置进度条到初始值
    /// </summary>
    public void ResetProgress()
    {
        CurrentProgress = initialProgress;
    }

    /// <summary>
    /// 立即设置进度条值
    /// </summary>
    /// <param name="newValue">新的进度值(0-100)</param>
    public void SetProgress(float newValue)
    {
        CurrentProgress = newValue;
    }

    /// <summary>
    /// 手动设置是否在范围内
    /// </summary>
    /// <param name="isInRange">是否在范围内</param>
    public void SetInRangeStatus(bool isInRange)
    {
        _isInRange = isInRange;
    }
    #endregion

    #region 验证方法
    /// <summary>
    /// 验证标签是否有效
    /// </summary>
    private bool IsTagValid(string tag)
    {
        return !string.IsNullOrEmpty(tag);
    }
    #endregion

    #region Gizmos绘制
    /// <summary>
    /// 在Scene视图中绘制范围Gizmos
    /// </summary>
    private void OnDrawGizmosSelected()
    {
        Gizmos.color = _isInRange ? Color.red : Color.green;

        if (detectionMode == DetectionMode.Position)
        {
            // 绘制当前物体的检测范围
            Gizmos.DrawWireSphere(transform.position, distanceRange);

            // 如果是攻击者，绘制所有目标的范围
            if (gameObject.CompareTag(attackerTag) && _targetObjects != null)
        {
            Gizmos.color = Color.blue;
            foreach (var target in _targetObjects)
            {
                if (target != null)
                    Gizmos.DrawWireSphere(target.transform.position, distanceRange);
            }
        }
        // 如果是目标，绘制所有攻击者的范围
        else if (gameObject.CompareTag(targetTag) && _attackerObjects != null)
        {
            Gizmos.color = Color.red;
            foreach (var attacker in _attackerObjects)
            {
                if (attacker != null)
                    Gizmos.DrawWireSphere(attacker.transform.position, distanceRange);
            }
        }
        }


        // 绘制进度条状态
        Vector3 progressGizmoPosition = transform.position + Vector3.up * 2f;
        string progressText = $"Progress: {Mathf.Round(CurrentProgress)}%";
        UnityEditor.Handles.Label(progressGizmoPosition, progressText);
    }
    #endregion
}

/// <summary>
/// 使用说明：
/// 1. 将此脚本挂载到需要检测的物体上
/// 2. 设置阵营标签：
///    - attackerTag：攻击者阵营标签
///    - targetTag：目标阵营标签
/// 3. 配置范围和进度参数：
///    - distanceRange：检测距离范围（半径）
///    - initialProgress：初始进度值(0-100)
///    - decreaseRate：在范围内时的降低速度(/秒)
///    - recoveryRate：不在范围内时的恢复速度(/秒)
/// 4. 在Inspector面板中绑定事件：
///    - onProgressComplete：进度为0时触发
///    - onProgressChanged：进度变化时触发(返回当前进度)
/// 5. 可选公共方法：
///    - ResetProgress()：重置进度到初始值
///    - SetProgress(float)：直接设置进度值
///    - SetInRangeStatus(bool)：手动设置是否在范围内
/// 
/// 注意事项：
/// - 确保场景中有带有攻击者和目标标签的物体
/// - 进度条值会自动限制在0-initialProgress之间(除非允许超过)
/// - Scene视图中会显示不同阵营的范围Gizmos和当前进度值
/// - 攻击者阵营物体将检测目标阵营物体，反之亦然
/// </summary>